package com.zhoudy.segmetlock;


import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SegmentDataWithLock {


    //分段锁持有map
    private Map<String, ReentrantLock> lockMap = new ConcurrentHashMap<String, ReentrantLock>();

    //分段持有主键数组map
    private Map<String, String[]> segmentMap = new HashMap<>();

    //分段前缀
    private final static String SEGMENT_PIX = "seg";

    //分段大小
    private final int segmentSize = 8;

    //总分段数
    private int segmentCnt = 0;

    /**
     * 按分段名称检查分段锁，没有则新建一个锁
     * @param segment
     * @return Lock
     */
    public Lock checkGetLock(String segment, boolean setDefault){
        ReentrantLock reentrantLock = lockMap.get(segment);
        if (reentrantLock == null && setDefault) {
            synchronized (this){
                reentrantLock = lockMap.get(segment);
                if (reentrantLock == null) {
                    reentrantLock = new ReentrantLock();
                    System.out.println("lock for " + segment + " not exists! so create a lock: " + reentrantLock);
                    lockMap.put(segment, reentrantLock);
                    return  reentrantLock;
                }
                return  reentrantLock;
            }
        }
        return  reentrantLock;
    }

    /**
     * 对数组进行分段并设置分段锁
     */
    public void blokFullWithSegmentation(String[] arr) {
        List<List<String>> segList=new ArrayList<>();
        List<String> mList= Arrays.asList(arr);
        //System.out.println(mList.toString());
        //开始分段
        this.delivedEachSubList(mList,segList,segmentSize);

        //为每个分段赋值及分段锁
        for (int i = 0; i < segList.size(); i++) {
            //System.out.println(segList.get(i).toString()+"");
            List<String> singleSegList = segList.get(i);
            segmentMap.put(this.SEGMENT_PIX.concat(String.valueOf(i)),  singleSegList.toArray(new String[0]));
            lockMap.put(this.SEGMENT_PIX.concat(String.valueOf(i)),new ReentrantLock());
            this.segmentCnt = segList.size();
        }
    }

    public static void delivedEachSubList(List<String> mList, List<List<String>> segList, int segmentSize) {
        if( mList.size()%segmentSize!=0) {
            for (int j = 0; j < mList.size() / segmentSize + 1; j++) {
                if ((j * segmentSize + segmentSize) < mList.size()) {
                    segList.add(mList.subList(j * segmentSize, j * segmentSize + segmentSize));//0-3,4-7,8-11    j=0,j+3=3   j=j*3+1
                } else if ((j * segmentSize + segmentSize) > mList.size()) {
                    segList.add(mList.subList(j * segmentSize, mList.size()));
                } else if (mList.size() < segmentSize) {
                    segList.add(mList.subList(0, mList.size()));
                }
            }
        }else if(mList.size()%segmentSize==0){
            for (int j = 0; j < mList.size() / segmentSize; j++) {
                if ((j * segmentSize + segmentSize) <= mList.size()) {
                    segList.add(mList.subList(j * segmentSize, j * segmentSize + segmentSize));//0-3,4-7,8-11    j=0,j+3=3   j=j*3+1
                } else if ((j * segmentSize+ segmentSize) > mList.size()) {
                    segList.add(mList.subList(j * segmentSize, mList.size()));
                } else if (mList.size() < segmentSize) {
                    segList.add(mList.subList(0, mList.size()));
                }
            }
        }
    }


    public void removeDataAndLockOfSegment(String segment){
        segmentMap.remove(segment);
        lockMap.remove(segment);
    }

    public Map<String, ReentrantLock> getLockMap() {
        return lockMap;
    }

    public Map<String, String[]> getSegmentMap() {
        return segmentMap;
    }

    public int getSegmentCnt() { return segmentCnt; }

    @Deprecated
    private void blokFullWithSegmentationx (String[] arr){
        int segmentCnt = 0;
        if (arr.length%segmentSize!=0){
            segmentCnt = arr.length/segmentSize +1;
        }
        int index=0;
        for (int i = 0; i < segmentCnt; i++) {
            String[] segArr = new String[segmentSize];
            for (int j = 0; j < segmentSize; j++) {
                segArr[j] = arr[index ];
                if (index+1<arr.length){
                    index++;
                }else {
                    break;
                }
            }
            segmentMap.put(this.SEGMENT_PIX.concat(String.valueOf(i)),segArr);
            lockMap.put(this.SEGMENT_PIX.concat(String.valueOf(i)),new ReentrantLock());
        }

    }

    public static void main(String[] args) {
        SegmentDataWithLock instance = new SegmentDataWithLock();
        String[] data = new String[32];
        for (int i = 0; i < 32; i++) {
            data[i] = "TestData".concat(String.valueOf(i));
        }

        instance.blokFullWithSegmentation(data);


        System.exit(0);
//        SegmentDataWithLock instance = new SegmentDataWithLock();
//        String[] data = new String[10];
//        for (int i = 0; i < 10; i++) {
//            data[i] = "TestData".concat(String.valueOf(i));
//        }

//        List<String[]> aa = getListIntArray(data, 3);
//
//        System.out.println(aa);

//        System.exit(0);
//        instance.blokFullWithSegmentation(data);
//
//        System.out.println(instance.segmentMap);

        Map map = new HashMap();
        map.put("a",1);
        map.put("b",2);
        map.put("c",3);

        System.out.println(map.get("a"));
        map.remove("a");
        System.out.println(map.get("a"));
        map.remove("d");

        List<String> list = new ArrayList<>(10);
        list.addAll(Arrays.asList("a","b","c" ));
        list.addAll(Arrays.asList("aa","bb","cv" ));
        for (String str: list) {
            System.out.println(str);
        }


    }
}
